package com.yanghui.lingyue.functions.ktBase

import com.icedata.sika.bridge.*
import com.icedata.sika.core.CommandProcessor
import com.icedata.sika.core.Sika
import com.icedata.sika.database.Column
import com.icedata.sika.database.Table
import com.icedata.sika.util.Logger
import com.yanghui.lingyue.data.Command
import com.yanghui.lingyue.functions.AbstractFunction
import com.yanghui.lingyue.functions.python.GetSatellitePosition
import com.yanghui.lingyue.utils.functionUtils.FunctionUtils
import java.util.*

object ArknightRandCard : AbstractFunction() {

    override val name: String = "ArknightRand"

    private val upSixArray = arrayOf("铃兰")
    private val upFiveArray = arrayOf("夜魔", "断崖")
    private val upFourArray = arrayOf("卡达")
    private val priorityArray = arrayOf<String>()

    private val six = LinkedList<String>()
    private val five = LinkedList<String>()
    private val four = LinkedList<String>()
    private val three = LinkedList<String>()
    private val upSix = LinkedList<String>()
    private val upFive = LinkedList<String>()
    private val upFour = LinkedList<String>()
    private val priority = LinkedList<String>()

    private const val upSixPossibility = 5
    private const val upFivePossibility = 5
    private const val upFourPossibility = 2


    override suspend fun parse(event: SikaEvent, sika: Sika): LinkedList<Command> {
        val command = LinkedList<Command>()
        if (event is SikaUserEvent) return command
        event as SikaGroupEvent
        if (event.sendGroup.id !in enableGroup) return command

        val param = FunctionUtils.extractKeyword(event, "抽卡")
        param?.let {
            command.add(Command(event, name, it))
        }
        return command
    }

    override suspend fun execute(command: Command, sika: Sika): CommandProcessor.Result {
        val messageBuilder = SikaMessageChainBuilder()
        val randNum: Int
        val result: RandResult
        try {
            randNum = command.param.toInt()
        } catch (e: NumberFormatException) {
            command.sendGroup?.sendMessage("你填写的好像不是数字哦")
                return CommandProcessor.Result.ADOPT
        }
        try {
            result = if (command.instruction.contains("-Treat")) {
                rand(randNum, 0.5)
            } else {
                rand(randNum, 0.0)
            }
        } catch (e: RandCardException) {
            command.sendGroup?.sendMessage("抽卡的数量不符合要求")
            return CommandProcessor.Result.ADOPT
        }
        messageBuilder.add(SikaQuoteMessage(command.message))
        messageBuilder.add(SikaAtMessage(command.sender.id))
        messageBuilder.add(
            SikaPlainMessage(
                when (randNum) {
                    in 1..20 -> "抽卡结果为\n" +
                            "六星:${result.sixResult}\n" +
                            "五星:${result.fiveResult}\n" +
                            "四星:${result.fourResult}\n" +
                            "三星${result.threeResult}"
                    else -> "抽卡结果为\n" +
                            "六星:${result.sixResult}\n" +
                            "五星:${result.fiveResult}\n" +
                            "四星:${result.fourResult.size}个\n" +
                            "三星:${result.threeResult.size}个"
                }
            )
        )
        for (n in result.sixResult) {
            if (isSixStar(n)) {
                messageBuilder.add(SikaPlainMessage("\n在第${result.sixResult.indexOf(n) + 1}个抽到六星:$n"))
            }
        }
        command.sendGroup?.sendMessage(messageBuilder)
        return CommandProcessor.Result.ADOPT
    }

    override fun filter(command: Command): Boolean {
        return command.instruction.startsWith(name)
    }

    @Throws(RandCardException::class)
    fun rand(num: Int, treat: Double): RandResult {
        val possibility = doubleArrayOf(0.02 + treat, 0.1 + treat, 0.6 + treat, 1 + treat)
        if (num > 100 || num <= 0) throw RandCardException("抽卡数量过多")
        val result = RandResult()
        var noSixNum = 0
        repeat(num) {
            val name = randOne(possibility)
            if (isSixStar(name)) {
                noSixNum = 0
                possibility[0] = 0.02
                possibility[1] = 0.1
                possibility[2] = 0.6
                possibility[3] = 1.0
                result.sixResult.add(name)
            } else
                noSixNum++
            when (getStar(name)) {
                5 -> result.fiveResult.add(name)
                4 -> result.fourResult.add(name)
                3 -> result.threeResult.add(name)
            }
            if (noSixNum > 50)
                for (j in 0..3) {
                    possibility[j] += 0.02
                }
            result.allResult.add(name)
        }
        return result
    }

    private fun randOne(possibility: DoubleArray): String {
        var randCache = Random().nextInt(100)
        return if (randCache < possibility[0] * 100) { // 6星
            // 先处理up干员
            randCache = Random().nextInt(10)
            if (randCache < upSixPossibility) // 出现up
            {
                upSix[Random().nextInt(upSix.size)]
            } else { // 池子歪了
                // 如果没有五倍权值
                if (priority.isEmpty())
                    six[Random().nextInt(six.size)]
                else {
                    val allNum: Int =
                        six.size + 5 * priority.size
                    randCache = Random().nextInt(allNum)
                    if (randCache < six.size)
                        six[randCache]
                    else
                        priority[0]
                }
            }
        } else if (randCache < possibility[1] * 100) {
            // 先处理up干员
            randCache = Random().nextInt(10)
            // 如果没有up
            if (upFive.isEmpty())
                five[Random().nextInt(five.size)]
            if (randCache < upFivePossibility) // 出现up
            {
                upFive[Random().nextInt(upFive.size)]
            } else { // 池子歪了
                five[Random().nextInt(five.size)]
            }
        } else if (randCache < possibility[2] * 100) {
            randCache = Random().nextInt(10)
            if (upFour.isEmpty())
                four[Random().nextInt(four.size)]
            if (randCache < upFourPossibility)
                upFour[Random().nextInt(upFour.size)]
            else
                four[Random().nextInt(four.size)]
        } else {
            three[Random().nextInt(three.size)]
        }
    }

    private fun isSixStar(name: String): Boolean {
        return upSix.contains(name) || priority.contains(name) || six.contains(name)
    }

    private fun getStar(name: String): Int {
        if (isSixStar(name)) return 6
        if (upFive.contains(name) || five.contains(name))
            return 5
        return if (four.contains(name) || upFour.contains(name))
            4
        else
            3
    }

//    fun rand(num: Int, treat: Double):

    class RandCardException(message: String) : Exception(message)

    class RandResult {
        val allResult = LinkedList<String>()
        val sixResult = LinkedList<String>()
        val fiveResult = LinkedList<String>()
        val fourResult = LinkedList<String>()
        val threeResult = LinkedList<String>()
    }

    @Table("RandCard", "", "operationID")
    class RandRecord(
        @Column("operationID")
        var operationID: Long,

        @Column("userID")
        var userID: Long,

        @Column("randNum")
        var randNum: Int,

        @Column("sixNum")
        var sixNum: Int,

        @Column("fiveNum")
        var fiveNum: Int
    ) {
        constructor() : this(0, 0, 0, 0, 0)
    }

    private val sixArray = arrayOf(
        "棘刺",
        "铃兰",
        "早露",
        "温蒂",
        "傀影",
        "风笛",
        "刻俄柏",
        "阿",
        "煌",
        "莫斯提马",
        "麦哲伦",
        "赫拉格",
        "黑",
        "陈",
        "斯卡蒂",
        "银灰",
        "塞雷娅",
        "星熊",
        "夜莺",
        "闪灵",
        "安洁莉娜",
        "艾雅法拉",
        "伊芙利特",
        "推进之王",
        "能天使",
        "森蚺",
        "史尔特尔",
        "瑕光",
        "泥岩",
        "山",
        "空弦",
        "凯尔希",
        "刻俄柏",
        "异客",
        "卡涅利安"
    )
    private val fiveArray = arrayOf(
        "安哲拉",
        "贾维",
        "蜜蜡",
        "断崖",
        "莱恩哈特",
        "月禾",
        "石棉",
        "极境",
        "巫恋",
        "慑砂",
        "惊蛰",
        "吽",
        "灰喉",
        "布洛卡",
        "苇草",
        "槐琥",
        "送葬人",
        "星极",
        "格劳克斯",
        "诗怀雅",
        "夜魔",
        "食铁兽",
        "狮蝎",
        "空",
        "真理",
        "初雪",
        "崖心",
        "守林人",
        "普罗旺斯",
        "可颂",
        "雷蛇",
        "红",
        "临光",
        "华法琳",
        "赫默",
        "梅尔",
        "天火",
        "陨星",
        "白金",
        "蓝毒",
        "幽灵鲨",
        "拉普兰德",
        "芙兰卡",
        "德克萨斯",
        "凛冬",
        "白面鸮",
        "燧石",
        "四月",
        "奥斯塔",
        "絮雨",
        "卡夫卡",
        "爱丽丝",
        "绮良"
    )
    private val fourArray = arrayOf(
        "孑",
        "卡达",
        "波登可",
        "刻刀",
        "宴",
        "安比尔",
        "梅",
        "红云",
        "桃金娘",
        "苏苏洛",
        "格雷伊",
        "猎蜂",
        "阿消",
        "地灵",
        "深海色",
        "古米",
        "蛇屠箱",
        "角峰",
        "调香师",
        "嘉维尔",
        "末药",
        "暗索",
        "砾",
        "慕斯",
        "霜叶",
        "缠丸",
        "杜宾",
        "红豆",
        "清道夫",
        "讯使",
        "白雪",
        "流星",
        "杰西卡",
        "远山",
        "夜烟",
        "酸糖",
        "芳汀",
        "泡泡",
        "杰克",
        "松果",
        "豆苗",
        "深靛"
    )
    private val threeArray = arrayOf(
        "斑点", "泡普卡", "月见夜", "空爆", "梓兰", "史都华德", "安塞尔", "芙蓉", "炎熔", "安德切尔", "克洛斯", "米格鲁", "卡缇", "梅兰莎", "翎羽", "香草", "芬"
    )

    init {
        six.addAll(sixArray)
        five.addAll(fiveArray)
        four.addAll(fourArray)
        three.addAll(threeArray)
        upSix.addAll(upSixArray)
        upFive.addAll(upFiveArray)
        upFour.addAll(upFourArray)
        priority.addAll(priorityArray)
        six.removeAll(upSix)
        six.removeAll(priority)
        five.removeAll(upFive)
        four.removeAll(upFour)
    }
}